home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
HPAVC
/
HPAVC CD-ROM.iso
/
GBCOPIER.ZIP
/
GBREAD.ARJ
/
READ.C
< prev
next >
Wrap
C/C++ Source or Header
|
1995-11-06
|
15KB
|
590 lines
#include <stdio.h>
#include <conio.h>
#include <time.h>
#define DELAY delay(wait_delay)
/* Change those defines to match your compiler. */
#define OUTPORT(port, val) outp(port, val); DELAY
#define INPORT(port) inp(port)
#define CTRL ctrl_port
#define DATA data_port
#define STATUS status_port
/*
* Bits for MUX (C B A):
* ~AUTOFDXT ~SCLINT ~STROBE
* Bits in CTRL register (7..0):
* N/A N/A N/A IRQEnable ~SCLINT INIT ~AUTOFDXT ~STROBE
*/
#define MASK 0x00
#define nSTROBE 0x01
#define nAUTOFDXT 0x02
#define INIT 0x04
#define nSCLINT 0x08
/* CTRL MUX */
#define GET_LOW MASK | nAUTOFDXT | nSCLINT | nSTROBE
#define GET_HIGH MASK | nAUTOFDXT | nSCLINT
#define LOW_ADDR MASK | nAUTOFDXT | nSTROBE
#define HIGH_ADDR MASK | nAUTOFDXT
#define SET_DATA MASK | nSCLINT | nSTROBE
#define DATA_REG MASK | nSCLINT
#define NOT_USED MASK | nSTROBE
#define NOP MASK
/* CTRL U3 */
#define MREQ MASK | INIT
/* Load a register: toggle CK (OFF and ON) */
#define LOAD(reg) OUTPORT(CTRL, reg); OUTPORT(CTRL, NOP)
/* Put data on the bus */
#define WRITE(val) OUTPORT(DATA, val)
/* Write data in bank-switch IC */
#define WRITE_BKSW WRITE(0x00); OUTPORT(CTRL, SET_DATA); \
WRITE(0x01); WRITE(0x00); OUTPORT(CTRL, NOP)
/* Write data in RAM */
#define WRITE_MEM WRITE(0x00); OUTPORT(CTRL, SET_DATA); \
OUTPORT(CTRL, SET_DATA | MREQ); WRITE(0x01); \
WRITE(0x00); OUTPORT(CTRL, NOP)
/*
* Bits read (7..0):
* BUSY ~ACKPR PE SLCT ERROR N/A N/A N/A
* Bits from REGISTER (D7..D4, D3..D0):
* SLCT PE BUSY ~ACK
*/
#define READ_LOW(val) OUTPORT(CTRL, GET_LOW); val = INPORT(STATUS)
#define READ_HIGH(val) OUTPORT(CTRL, GET_HIGH); val = INPORT(STATUS)
#define READ_MEM_LOW(val) OUTPORT(CTRL, GET_LOW | MREQ); val = INPORT(STATUS)
#define READ_MEM_HIGH(val) OUTPORT(CTRL, GET_HIGH | MREQ); val = INPORT(STATUS)
#define D7(val) (val & 0x10) << 3
#define D6(val) (val & 0x20) << 1
#define D5(val) ((val ^ 0x80) & 0x80) >> 2
#define D4(val) (val & 0x40) >> 2
#define D3(val) (val & 0x10) >> 1
#define D2(val) (val & 0x20) >> 3
#define D1(val) ((val ^ 0x80) & 0x80) >> 6
#define D0(val) (val & 0x40) >> 6
#define CONVERT(l, h) D7(h) | D6(h) | D5(h) | D4(h) | D3(l) | D2(l) | D1(l) | D0(l)
#define NO_MBC 0
#define MBC1 1
#define MBC2 2
#ifdef MK_FP
#undef MK_FP
#endif
#define MK_FP(seg, ofs) ((void far *) ((unsigned long) (seg)<<16|(ofs)))
char *type[] = {
"ROM ONLY", "ROM+MBC1", "ROM+MBC1+RAM", "ROM+MBC1+RAM+BATTERY",
"UNKNOWN", "ROM+MBC2", "ROM+MBC2+BATTERY"
};
int rom[] = { 32, 64, 128, 256, 512 };
int ram[] = { 0, 2, 8, 32 };
int mbc[] = { NO_MBC, MBC1, MBC1, MBC1, MBC2, MBC2 };
int wait_delay;
unsigned ctrl_port;
unsigned data_port;
unsigned status_port;
void usage()
{
printf("Usage: read [-p int] [-w int] [-t | -d | -a | -s file | -b file | -r file]\n");
printf("\t-p\tSpecify the port to use (default is 1 = LPT1)\n");
printf("\t-w\tSpecify the time to wait between accesses to the cartridge\n");
printf("\t-t\tDebug mode (if the cartridge reader don't work)\n");
printf("\t-t\tTest the cartridge reader\n");
printf("\t-a\tAnalyze the cartridge\n");
printf("\t-s\tSave the cartridge in a file\n");
printf("\t-b\tBackup the SRAM and save it in a file\n");
printf("\t-r\tRestore the SRAM from a file\n");
}
int init_port(int port)
{
data_port = *(unsigned far *)MK_FP(0x0040, 6 + 2*port);
if(data_port == 0)
{
printf("Can't find address of parallel port %d...\n", port);
exit(1);
} else {
status_port = data_port + 1;
ctrl_port = data_port + 2;
printf("Parallel port %d is located at %X-%X\n", port, data_port, ctrl_port);
}
}
void delay(int i)
{
while(i--);
}
void read_data(FILE *fp, int type, int sizekB)
{
int bank, page, byte, nbbank;
unsigned char low, high;
/* One bank is 16k bytes */
nbbank = sizekB / 16;
for(bank = 0; bank < nbbank; bank++) {
printf("Reading bank %d\n", bank);
if(bank) {
WRITE(bank);
LOAD(DATA_REG);
WRITE(0x21);
LOAD(HIGH_ADDR);
WRITE(0x00);
LOAD(LOW_ADDR);
WRITE_BKSW;
}
for(page = (bank ? 0x40 : 0); page < (bank ? 0x80 : 0x40); page++) {
printf(".");
WRITE(page);
LOAD(HIGH_ADDR);
for(byte = 0; byte <= 0xFF; byte++) {
WRITE(byte);
LOAD(LOW_ADDR);
READ_LOW(low);
READ_HIGH(high);
fputc(CONVERT(low, high), fp);
}
}
printf("\n");
}
}
void read_sram(FILE *fp, int type, int sizekB)
{
int bank, page, byte, nbbank, banksize;
unsigned char low, high;
if(type == MBC1) {
/* One bank is 8k bytes */
nbbank = sizekB / 8;
if(nbbank == 0) {
nbbank = 1;
banksize = sizekB << 2;
} else
banksize = 0x20;
} else {
/* SRAM is 512 * 4 bits */
nbbank = 1;
banksize = 0x02;
}
/* Initialize the bank-switch IC */
WRITE(0x0A);
LOAD(DATA_REG);
WRITE(0x00);
LOAD(HIGH_ADDR);
WRITE(0x00);
LOAD(LOW_ADDR);
WRITE_BKSW;
for(bank = 0; bank < nbbank; bank++) {
if(type == MBC1) {
printf("Reading bank %d\n", bank);
WRITE(bank);
LOAD(DATA_REG);
WRITE(0x40);
LOAD(HIGH_ADDR);
WRITE(0x00);
LOAD(LOW_ADDR);
WRITE_BKSW;
}
for(page = 0xA0; page < 0xA0 + banksize; page++) {
printf(".");
WRITE(page);
LOAD(HIGH_ADDR);
for(byte = 0; byte <= 0xFF; byte++) {
WRITE(byte);
LOAD(LOW_ADDR);
READ_MEM_LOW(low);
READ_MEM_HIGH(high);
fputc(CONVERT(low, high), fp);
}
}
printf("\n");
}
}
void write_sram(FILE *fp, int type, int sizekB)
{
int bank, page, byte, nbbank, banksize;
unsigned char low, high;
if(type == MBC1) {
/* One bank is 8k bytes */
nbbank = sizekB / 8;
if(nbbank == 0) {
nbbank = 1;
banksize = sizekB << 2;
} else
banksize = 0x20;
} else {
/* SRAM is 512 * 4 bits */
nbbank = 1;
banksize = 0x02;
}
/* Initialize the bank-switch IC */
WRITE(0x0A);
LOAD(DATA_REG);
WRITE(0x00);
LOAD(HIGH_ADDR);
WRITE(0x00);
LOAD(LOW_ADDR);
WRITE_BKSW;
for(bank = 0; bank < nbbank; bank++) {
if(type == MBC1) {
printf("Writing bank %d\n", bank);
WRITE(bank);
LOAD(DATA_REG);
WRITE(0x40);
LOAD(HIGH_ADDR);
WRITE(0x00);
LOAD(LOW_ADDR);
WRITE_BKSW;
}
for(page = 0xA0; page < 0xA0 + banksize; page++) {
printf(".");
WRITE(page);
LOAD(HIGH_ADDR);
for(byte = 0; byte <= 0xFF; byte++) {
if(feof(fp)) {
printf("Unexpected EOF\n");
exit(1);
}
WRITE(byte);
LOAD(LOW_ADDR);
WRITE(fgetc(fp));
LOAD(DATA_REG);
WRITE_MEM;
}
}
printf("\n");
}
}
void read_header(unsigned char *h)
{
int byte, index = 0;
unsigned char low, high;
WRITE(0x01);
LOAD(HIGH_ADDR);
for(byte = 0; byte < 0x50; byte++) {
WRITE(byte);
LOAD(LOW_ADDR);
READ_LOW(low);
READ_HIGH(high);
h[index++] = CONVERT(low, high);
}
printf("Game name: %s\n", &h[0x34]);
printf("Cartridge type: %d(%s)\n", h[0x47], type[h[0x47]]);
printf("ROM size: %d(%d kB)\n", h[0x48], rom[h[0x48]]);
printf("RAM size: %d(%d kB)\n", h[0x49], ram[h[0x49]]);
}
void test()
{
int addr, errors;
unsigned char low, high;
printf("Connect A0..A7 to D0..D7 and press <RETURN>\n");
getch();
for(addr = 0, errors = 0; addr < 0xFF; addr++) {
WRITE(addr);
LOAD(LOW_ADDR);
READ_LOW(low);
READ_HIGH(high);
if(CONVERT(low, high) != addr)
errors++;
}
printf("%d errors (%d%%)\n\n", errors, errors*100/0xFF);
printf("Connect A8..A15 to D0..D7 and press <RETURN>\n");
getch();
for(addr = 0, errors = 0; addr < 0xFF; addr++) {
WRITE(addr);
LOAD(HIGH_ADDR);
READ_LOW(low);
READ_HIGH(high);
if(CONVERT(low, high) != addr)
errors++;
}
printf("%d errors (%d%%)\n\n", errors, errors*100/0xFF);
}
void debug()
{
int i = 0;
printf("Check pins <3,4,7,8,13,14,17,18> of U2, U3 or U5\n");
OUTPORT(DATA, 0x00);
printf("They should all be low. Press <RETURN>\n");
getch();
OUTPORT(DATA, 0xFF);
printf("They should all be high. Press <RETURN>\n");
getch();
printf("End of test %d.\n\n", ++i);
printf("Check pins <15,14,13,12,11,10,9,7> of U8\n");
OUTPORT(CTRL, GET_LOW);
printf("Pin 15 should be low, others should be high. Press <RETURN>\n");
getch();
OUTPORT(CTRL, GET_HIGH);
printf("Pin 14 should be low, others should be high. Press <RETURN>\n");
getch();
OUTPORT(CTRL, SET_DATA);
printf("Pin 13 should be low, others should be high. Press <RETURN>\n");
getch();
OUTPORT(CTRL, DATA_REG);
printf("Pin 12 should be low, others should be high. Press <RETURN>\n");
getch();
OUTPORT(CTRL, LOW_ADDR);
printf("Pin 11 should be low, others should be high. Press <RETURN>\n");
getch();
OUTPORT(CTRL, HIGH_ADDR);
printf("Pin 10 should be low, others should be high. Press <RETURN>\n");
getch();
OUTPORT(CTRL, NOT_USED);
printf("Pin 9 should be low, others should be high. Press <RETURN>\n");
getch();
OUTPORT(CTRL, NOP);
printf("Pin 8 should be low, others should be high. Press <RETURN>\n");
getch();
printf("End of test %d.\n\n", ++i);
printf("Check pins <2,5,6,9,12,15,16,19> of U2\n");
WRITE(0x01);
LOAD(LOW_ADDR);
printf("Pin 2 should be high, others should be low. Press <RETURN>\n");
getch();
WRITE(0x02);
LOAD(LOW_ADDR);
printf("Pin 5 should be high, others should be low. Press <RETURN>\n");
getch();
WRITE(0x04);
LOAD(LOW_ADDR);
printf("Pin 6 should be high, others should be low. Press <RETURN>\n");
getch();
WRITE(0x08);
LOAD(LOW_ADDR);
printf("Pin 9 should be high, others should be low. Press <RETURN>\n");
getch();
WRITE(0x10);
LOAD(LOW_ADDR);
printf("Pin 12 should be high, others should be low. Press <RETURN>\n");
getch();
WRITE(0x20);
LOAD(LOW_ADDR);
printf("Pin 15 should be high, others should be low. Press <RETURN>\n");
getch();
WRITE(0x40);
LOAD(LOW_ADDR);
printf("Pin 16 should be high, others should be low. Press <RETURN>\n");
getch();
WRITE(0x80);
LOAD(LOW_ADDR);
printf("Pin 19 should be high, others should be low. Press <RETURN>\n");
getch();
printf("End of test %d.\n\n", ++i);
printf("Check pins <2,5,6,9,12,15,16,19> of U3\n");
WRITE(0x01);
LOAD(HIGH_ADDR);
printf("Pin 2 should be high, others should be low. Press <RETURN>\n");
getch();
WRITE(0x02);
LOAD(HIGH_ADDR);
printf("Pin 5 should be high, others should be low. Press <RETURN>\n");
getch();
WRITE(0x04);
LOAD(HIGH_ADDR);
printf("Pin 6 should be high, others should be low. Press <RETURN>\n");
getch();
WRITE(0x08);
LOAD(HIGH_ADDR);
printf("Pin 9 should be high, others should be low. Press <RETURN>\n");
getch();
WRITE(0x10);
LOAD(HIGH_ADDR);
printf("Pin 12 should be high, others should be low. Press <RETURN>\n");
getch();
WRITE(0x20);
LOAD(HIGH_ADDR);
printf("Pin 15 should be high, others should be low. Press <RETURN>\n");
getch();
WRITE(0x40);
LOAD(HIGH_ADDR);
printf("Pin 16 should be high, others should be low. Press <RETURN>\n");
getch();
WRITE(0x80);
LOAD(HIGH_ADDR);
printf("Pin 19 should be high, others should be low. Press <RETURN>\n");
getch();
printf("End of test %d.\n\n", ++i);
printf("Check pins <2,5,6,9,12,15,16,19> of U5\n");
WRITE(0x01);
LOAD(DATA_REG);
printf("Pin 2 should be high, others should be low. Press <RETURN>\n");
getch();
WRITE(0x02);
LOAD(DATA_REG);
printf("Pin 5 should be high, others should be low. Press <RETURN>\n");
getch();
WRITE(0x04);
LOAD(DATA_REG);
printf("Pin 6 should be high, others should be low. Press <RETURN>\n");
getch();
WRITE(0x08);
LOAD(DATA_REG);
printf("Pin 9 should be high, others should be low. Press <RETURN>\n");
getch();
WRITE(0x10);
LOAD(DATA_REG);
printf("Pin 12 should be high, others should be low. Press <RETURN>\n");
getch();
WRITE(0x20);
LOAD(DATA_REG);
printf("Pin 15 should be high, others should be low. Press <RETURN>\n");
getch();
WRITE(0x40);
LOAD(DATA_REG);
printf("Pin 16 should be high, others should be low. Press <RETURN>\n");
getch();
WRITE(0x80);
LOAD(DATA_REG);
printf("Pin 19 should be high, others should be low. Press <RETURN>\n");
getch();
printf("End of test %d.\n\n", ++i);
printf("Check pins <3,6,8> of U7\n");
OUTPORT(CTRL, NOP | MREQ);
printf("Pin 6 should be low. Press <RETURN>\n");
getch();
OUTPORT(CTRL, NOP);
printf("Pin 6 should be high. Press <RETURN>\n");
getch();
OUTPORT(CTRL, SET_DATA);
printf("Pin 3 should be high, pin 8 should be low. Press <RETURN>\n");
getch();
OUTPORT(CTRL, NOP);
printf("Pin 3 should be low, pin 8 should be high. Press <RETURN>\n");
getch();
printf("End of test %d.\n\n", ++i);
printf("Check pins <1,19> of U4\n");
OUTPORT(CTRL, NOP);
printf("Pin 1 and 19 should be high. Press <RETURN>\n");
getch();
OUTPORT(CTRL, GET_HIGH);
printf("Pin 1 should be low, pin 19 should be high. Press <RETURN>\n");
getch();
OUTPORT(CTRL, GET_LOW);
printf("Pin 1 should be high, pin 19 should be low. Press <RETURN>\n");
getch();
printf("End of test %d.\n\n", ++i);
printf("If all tests passed and 'read -a' doesn't read correctly the header,\n");
printf("please e-mail me.\n");
}
void main(int argc, char **argv)
{
int arg;
FILE *fp;
unsigned char header[0x50];
if(argc < 2) {
usage();
exit(1);
}
wait_delay = 10;
init_port(1);
for(arg = 1; arg < argc; arg++) {
if(argv[arg][0] != '-') {
usage();
exit(1);
}
switch(argv[arg][1]) {
case 'p':
case 'P':
init_port(atoi(argv[++arg]));
break;
case 'w':
case 'W':
wait_delay = atoi(argv[++arg]);
break;
case 'd':
case 'D':
debug();
break;
case 't':
case 'T':
test();
break;
case 'a':
case 'A':
read_header(header);
break;
case 's':
case 'S':
if((fp = fopen(argv[++arg], "wb")) == NULL) {
printf("Error opening file %s\n", argv[arg]);
exit(1);
}
read_header(header);
read_data(fp, mbc[header[0x47]], rom[header[0x48]]);
fclose(fp);
break;
case 'b':
case 'B':
if((fp = fopen(argv[++arg], "wb")) == NULL) {
printf("Error opening file %s\n", argv[arg]);
exit(1);
}
read_header(header);
read_sram(fp, mbc[header[0x47]], ram[header[0x49]]);
fclose(fp);
break;
case 'r':
case 'R':
if((fp = fopen(argv[++arg], "rb")) == NULL) {
printf("Error opening file %s\n", argv[arg]);
exit(1);
}
read_header(header);
write_sram(fp, mbc[header[0x47]], ram[header[0x49]]);
fclose(fp);
break;
default:
usage();
exit(1);
}
}
exit(0);
}